package com.yunhe.energy.service.data.impl;

import com.yunhe.common.model.device.Analog;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.energy.client.AuthorityClient;
import com.yunhe.energy.client.DeviceClient;
import com.yunhe.energy.client.MeasHistoryClient;
import com.yunhe.energy.client.MeasRealtimeClient;
import com.yunhe.common.constant.DeviceConsts;
import com.yunhe.common.constant.EnergyConsts;
import com.yunhe.energy.domain.data.ElectricityDay;
import com.yunhe.energy.domain.data.ElectricityDetail;
import com.yunhe.energy.domain.data.ElectricityMonth;
import com.yunhe.energy.domain.data.pk.ElectricityPK;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.energy.model.CompanySort;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.model.company.Company;
import com.yunhe.common.model.data.Measurement;
import com.yunhe.energy.repository.data.ElectricityDayRepository;
import com.yunhe.energy.repository.data.ElectricityMonthRepository;
import com.yunhe.energy.service.data.ElectricityService;
import com.yunhe.common.util.QueryUtil;
import com.yunhe.common.util.CollectionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 电量Service
 * @author liuronglei
 * @desc 电量服务类实现
 */
@Service
public class ElectricityServiceImpl implements ElectricityService {
    @Autowired
    private ElectricityDayRepository electricityDayRepository;
    @Autowired
    private ElectricityMonthRepository electricityMonthRepository;
    @Autowired
    private AuthorityClient authorityClient;
    @Autowired
    private MeasHistoryClient measHistoryClient;
    @Autowired
    private MeasRealtimeClient measRealtimeClient;

    @Autowired
    private DeviceClient deviceClient;

    /**
     * 获得电量对象PK
     * @param id 数据ID
     * @param dtime 时间
     */
    private ElectricityPK getElectricityPK(Long id, Date dtime) {
        ElectricityPK pk = new ElectricityPK();
        pk.setDeviceId(id);
        pk.setDtime(dtime);
        return pk;
    }

    /**
     * 获得查询参数
     * @param deviceId 对象ID
     * @param dtime 时间范围
     */
    private Specification getSpecification(Long deviceId, List<Date> dtime) {
        Specification spec = (root, query, cb) -> {
            List<Predicate> criteria = new ArrayList<>();
            if (deviceId != null) {
                Path<Long> deviceIdPath = root.get("deviceId");
                criteria.add(cb.equal(deviceIdPath, deviceId));
            }
            if (dtime != null) {
                Path<Date> dtimePath = root.get("dtime");
                if (dtime.size() == 1) {
                    criteria.add(cb.equal(dtimePath, dtime.get(0)));
                } else if (dtime.size() == 2) {
                    criteria.add(cb.between(dtimePath, dtime.get(0), dtime.get(1)));
                }
            }
            if (criteria.size() == 1) {
                query.where(criteria.get(0));
            } else {
                query.where(criteria.toArray(new Predicate[0]));
            }
            return null;
        };
        return spec;
    }

//    /**
//     * 新增电量对象（明细）
//     * @param electricity 电量对象
//     */
//    @Transactional
//    public ElectricityDetail createElectricityDetail(ElectricityDetail electricity)
//            throws ArgumentErrorException, UniqueConstraintsException {
//        ElectricityDetail newElectricity = electricityDetailRepository.save(electricity);
//        return newElectricity;
//    }

    /**
     * 新增电量对象（日）
     * @param electricity 电量对象
     */
    @Override
    @Transactional
    public ElectricityDay createElectricityDay(ElectricityDay electricity)
            throws ArgumentErrorException, UniqueConstraintsException {
        ElectricityDay newElectricity = electricityDayRepository.save(electricity);
        return newElectricity;
    }

    /**
     * 新增电量对象（月）
     * @param electricity 电量对象
     */
    @Override
    @Transactional
    public ElectricityMonth createElectricityMonth(ElectricityMonth electricity)
            throws ArgumentErrorException, UniqueConstraintsException {
        ElectricityMonth newElectricity = electricityMonthRepository.save(electricity);
        return newElectricity;
    }

//    /**
//     * 批量新增电量对象（明细）
//     * @param electricityList 电量对象列表
//     */
//    @Transactional
//    public Iterable<ElectricityDetail> createElectricityDetail(List<ElectricityDetail> electricityList)
//            throws ArgumentErrorException, UniqueConstraintsException {
//        return null;
//    }

    /**
     * 批量新增电量对象（日）
     * @param electricityList 电量对象列表
     */
    @Transactional
    @Override
    public Iterable<ElectricityDay> createElectricityDay(List<ElectricityDay> electricityList)
            throws ArgumentErrorException, UniqueConstraintsException {
        Iterable<ElectricityDay> newElectricitys = electricityDayRepository.saveAll(electricityList);
        return newElectricitys;
    }

    /**
     * 批量新增电量对象（月）
     * @param electricityList 电量对象列表
     */
    @Override
    @Transactional
    public Iterable<ElectricityMonth> createElectricityMonth(List<ElectricityMonth> electricityList)
            throws ArgumentErrorException, UniqueConstraintsException {
        Iterable<ElectricityMonth> newElectricitys = electricityMonthRepository.saveAll(electricityList);
        return newElectricitys;
    }

//    /**
//     * 根据单位编号和时间删除电量对象（明细）
//     * @param pointNumber 点号
//     * @param dtime 时间
//     */
//    @Transactional
//    public void deleteElectricityDetail(Long pointNumber, Date dtime) {
//        ElectricityPK pk = getElectricityPK(pointNumber, dtime);
//        electricityDetailRepository.delete(pk);
//    }

    /**
     * 根据对象ID和时间删除电量对象（日）
     * @param deviceId 对象ID
     * @param dtime 时间
     */
    @Transactional
    public void deleteElectricityDay(Long deviceId, Date dtime) {
        ElectricityPK pk = getElectricityPK(deviceId, dtime);
        electricityDayRepository.deleteById(pk);
    }

    /**
     * 根据对象ID和时间删除电量对象（月）
     * @param deviceId 对象ID
     * @param dtime 时间
     */
    @Transactional
    public void deleteElectricityMonth(Long deviceId, Date dtime) {
        ElectricityPK pk = getElectricityPK(deviceId, dtime);
        electricityMonthRepository.deleteById(pk);
    }

//    /**
//     * 更新电量（明细）
//     * @param firmName 单位编号
//     * @param dtime 时间
//     * @param val 值
//     */
//    @Transactional
//    public ElectricityDetail updateElectricityDetail(String firmName, Date dtime, Double val)
//            throws ObjectNotFoundException {
//        ElectricityPK pk = getElectricityPK(firmName, dtime);
//        ElectricityDetail electricity = electricityDetailRepository.findOne(pk);
//        if (electricity == null) {
//            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            throw new ObjectNotFoundException("找不到单位编号为" + firmName
//                    + "，时间为" + timeFormat.format(dtime) + "的电量对象");
//        }
//        electricity.setVal(val);
//        ElectricityDetail newElectricity = electricityDetailRepository.save(electricity);
//        return newElectricity;
//    }

    /**
     * 更新电量（日）
     * @param deviceId 对象ID
     * @param dtime 时间
     * @param val 值
     */
    @Transactional
    public ElectricityDay updateElectricityDay(Long deviceId, Date dtime, Double val)
            throws ObjectNotFoundException {
        ElectricityPK pk = getElectricityPK(deviceId, dtime);
        Optional<ElectricityDay> electricityOpt = electricityDayRepository.findById(pk);
        if (!electricityOpt.isPresent()) {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            throw new ObjectNotFoundException("找不到对象ID为" + deviceId
                    + "，时间为" + timeFormat.format(dtime) + "的电量对象");
        }
        ElectricityDay electricity = electricityOpt.get();
        electricity.setVal(val);
        ElectricityDay newElectricity = electricityDayRepository.save(electricity);
        return newElectricity;
    }

    /**
     * 更新电量（月）
     * @param deviceId 对象ID
     * @param dtime 时间
     * @param val 值
     */
    @Transactional
    public ElectricityMonth updateElectricityMonth(Long deviceId, Date dtime, Double val)
            throws ObjectNotFoundException {
        ElectricityPK pk = getElectricityPK(deviceId, dtime);
        Optional<ElectricityMonth> electricityOpt = electricityMonthRepository.findById(pk);
        if (!electricityOpt.isPresent()) {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            throw new ObjectNotFoundException("找不到对象ID为" + deviceId
                    + "，时间为" + timeFormat.format(dtime) + "的电量对象");
        }
        ElectricityMonth electricity = electricityOpt.get();
        electricity.setVal(val);
        ElectricityMonth newElectricity = electricityMonthRepository.save(electricity);
        return newElectricity;
    }

    private Long getElectricityPointNumber(Long deviceId, String typeCode) throws ObjectNotFoundException {
        Analog analog = deviceClient.getAnalogsByDevIdAndTypeCode(deviceId, typeCode, null,null).getBody().getResults();
        return analog == null ? null : analog.getPointNumber();
    }

    private Map<String, Object> getPageParamMap(PageParam pageParam) {
        Map<String, Object> map = new HashMap<>();
        if (pageParam == null) {
            return map;
        }
        map.put("page", pageParam.getPage());
        map.put("size", pageParam.getSize());
        map.put("sort", pageParam.getSort());
        return map;
    }

    /**
     * 根据条件获得电量对象列表（明细）
     * @param deviceId 对象ID
     * @param dtime 时间范围
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<ElectricityDetail> findElectricityDetail(Long deviceId,
                                                             List<Date> dtime,
                                                             PageParam pageParam)
            throws ObjectNotFoundException {
        //把结束日期往后扩1秒
        if (dtime.size() == 2) {
            dtime.get(1).setTime(dtime.get(1).getTime() + 1000);
        }
        Map<String, ElectricityDetail> map = new HashMap<>();

        List<ElectricityDetail> results = new ArrayList<>();
        //查询正向有功总电度点号
        Analog powerAllAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerAll.value(), null,null).getBody().getResults();
        if(powerAllAnalog != null){
            //通过点号和日期查询历史量测数据
            List<Measurement> measurementList = measHistoryClient.getMeasurements(
                    powerAllAnalog.getPointNumber(), dtime, getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementList)){
                for (int i = 0; i < measurementList.size() - 1; i++) {
                    Measurement measurement = measurementList.get(i);
                    Measurement measurementNext = measurementList.get(i + 1);
                    ElectricityDetail electricity = new ElectricityDetail();
                    electricity.setDeviceId(deviceId);
                    electricity.setDtime(DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()));
                    electricity.setVal(measurementNext.getVal() - measurement.getVal());
                    results.add(electricity);
                    map.put(measurement.getDtime().toString(), electricity);
                }
            }
        }

        //查询当前尖峰电度点号
        Analog powerSharpAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerSharp.value(), null,null).getBody().getResults();
        if(powerSharpAnalog != null){
            List<Measurement> measurementSharpList = measHistoryClient.getMeasurements(
                    powerSharpAnalog.getPointNumber(), dtime, getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementSharpList)){
                for (int i = 0; i < measurementSharpList.size() - 1; i++) {
                    Measurement measurement = measurementSharpList.get(i);
                    Measurement measurementNext = measurementSharpList.get(i + 1);
                    ElectricityDetail electricity = getElectricityDetail(map, DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()), deviceId);
                    electricity.setSharp(measurementNext.getVal() - measurement.getVal());
                }
            }
        }

        //查询当前峰电度点号
        Analog powerPeakAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerPeak.value(), null,null).getBody().getResults();
        if(powerPeakAnalog != null){
            List<Measurement> measurementPeakList = measHistoryClient.getMeasurements(
                    powerPeakAnalog.getPointNumber(), dtime, getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementPeakList)){
                for (int i = 0; i < measurementPeakList.size() - 1; i++) {
                    Measurement measurement = measurementPeakList.get(i);
                    Measurement measurementNext = measurementPeakList.get(i + 1);
                    ElectricityDetail electricity = getElectricityDetail(map, DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()), deviceId);
                    electricity.setPeak(measurementNext.getVal() - measurement.getVal());
                }
            }
        }

        //查询当前平电度点号
        Analog powerFlatAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerFlat.value(), null,null).getBody().getResults();
        if(powerFlatAnalog != null){
            List<Measurement> measurementFlatList = measHistoryClient.getMeasurements(
                    powerFlatAnalog.getPointNumber(), dtime, getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementFlatList)){
                for (int i = 0; i < measurementFlatList.size() - 1; i++) {
                    Measurement measurement = measurementFlatList.get(i);
                    Measurement measurementNext = measurementFlatList.get(i + 1);
                    ElectricityDetail electricity = getElectricityDetail(map, DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()), deviceId);
                    electricity.setFlat(measurementNext.getVal() - measurement.getVal());
                }
            }
        }

        //查询当前谷电度点号
        Analog powerValleyAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerValley.value(), null,null).getBody().getResults();
        if(powerValleyAnalog != null){
            List<Measurement> measurementValleyList = measHistoryClient.getMeasurements(
                    powerValleyAnalog.getPointNumber(), dtime, getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementValleyList)){
                for (int i = 0; i < measurementValleyList.size() - 1; i++) {
                    Measurement measurement = measurementValleyList.get(i);
                    Measurement measurementNext = measurementValleyList.get(i + 1);
                    ElectricityDetail electricity = getElectricityDetail(map, DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()), deviceId);
                    electricity.setValley(measurementNext.getVal() - measurement.getVal());
                }
            }
        }

        return results;
    }

    private ElectricityDetail getElectricityDetail(Map<String, ElectricityDetail> map, Date dtime, Long deviceId) {
        ElectricityDetail electricity = map.get(dtime.toString());
        if (electricity == null) {
            electricity = new ElectricityDetail();
            electricity.setDeviceId(deviceId);
            electricity.setDtime(dtime);
            map.put(dtime.toString(), electricity);
        }
        return electricity;
    }

    /**
     * 根据条件获得电量对象递增列表（明细）
     * @param deviceId 对象ID
     * @param dtime 时间范围
     * @param pageParam 分页对象
     */
    public Iterable<ElectricityDetail> findElectricityDetailWithIncrease(Long deviceId,
                                                                         List<Date> dtime,
                                                                         PageParam pageParam)
            throws ObjectNotFoundException {
        Map<String, ElectricityDetail> map = new HashMap<>();
        List<ElectricityDetail> results = new ArrayList<>();
        //查询正向有功总电度
        Analog powerAllAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerAll.value(), null,null).getBody().getResults();
        if(powerAllAnalog != null){
            //通过点号和日期查询历史量测数据
            List<Measurement> measurementList = measHistoryClient.getMeasurements(
                    powerAllAnalog.getPointNumber(), null,
                    getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementList)){
                Double minVal = Double.MAX_VALUE;
                //第一次循环，获取最小的值
                for (Measurement measurement : measurementList) {
                    if (measurement.getVal() < minVal) {
                        minVal = measurement.getVal();
                    }
                }
                //第二次循环，填充数据
                for (Measurement measurement : measurementList) {
                    ElectricityDetail electricity = new ElectricityDetail();
                    electricity.setDeviceId(deviceId);
                    electricity.setDtime(DateTimeUtils.formatToDate(measurement.getDtime(),DateTimeUtils.PATTERN.DATETIME.value()));
                    electricity.setVal(measurement.getVal() - minVal);
                    results.add(electricity);
                    map.put(measurement.getDtime().toString(), electricity);
                }
            }
        }

        //查询当前尖峰电度点号
        Analog powerSharpAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerSharp.value(), null,null).getBody().getResults();
        if(powerSharpAnalog != null){
            List<Measurement> measurementSharpList = measHistoryClient.getMeasurements(
                    powerSharpAnalog.getPointNumber(), null,
                    getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementSharpList)){
                Double minVal = Double.MAX_VALUE;
                //第一次循环，获取最小的值
                for (Measurement measurement : measurementSharpList) {
                    if (measurement.getVal() < minVal) {
                        minVal = measurement.getVal();
                    }
                }
                //第二次循环，填充数据
                for (Measurement measurement : measurementSharpList) {
                    ElectricityDetail electricity = map.get(measurement.getDtime().toString());
                    electricity.setSharp(measurement.getVal() - minVal);
                }
            }
        }

        //查询当前峰电度点号
        Analog powerPeakAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerPeak.value(), null,null).getBody().getResults();
        if(powerPeakAnalog != null){
            List<Measurement> measurementPeakList = measHistoryClient.getMeasurements(
                    powerPeakAnalog.getPointNumber(), null,
                    getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementPeakList)){
                Double minVal = Double.MAX_VALUE;
                //第一次循环，获取最小的值
                for (Measurement measurement : measurementPeakList) {
                    if (measurement.getVal() < minVal) {
                        minVal = measurement.getVal();
                    }
                }
                //第二次循环，填充数据
                for (Measurement measurement : measurementPeakList) {
                    ElectricityDetail electricity = map.get(measurement.getDtime().toString());
                    electricity.setPeak(measurement.getVal() - minVal);
                }
            }
        }

        //查询当前平电度点号
        Analog powerFlatAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerFlat.value(), null,null).getBody().getResults();
        if(powerFlatAnalog != null){
            List<Measurement> measurementFlatList = measHistoryClient.getMeasurements(
                    powerFlatAnalog.getPointNumber(), null,
                    getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementFlatList)){
                Double minVal = Double.MAX_VALUE;
                //第一次循环，获取最小的值
                for (Measurement measurement : measurementFlatList) {
                    if (measurement.getVal() < minVal) {
                        minVal = measurement.getVal();
                    }
                }
                //第二次循环，填充数据
                for (Measurement measurement : measurementFlatList) {
                    ElectricityDetail electricity = map.get(measurement.getDtime().toString());
                    electricity.setFlat(measurement.getVal() - minVal);
                }
            }
        }

        //查询当前谷电度点号
        Analog powerValleyAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, DeviceConsts.POINT_DATA_TYPE.PowerValley.value(), null,null).getBody().getResults();
        if(powerValleyAnalog != null){
            List<Measurement> measurementValleyList = measHistoryClient.getMeasurements(
                    powerValleyAnalog.getPointNumber(), null,
                    getPageParamMap(pageParam)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurementValleyList)){
                Double minVal = Double.MAX_VALUE;
                //第一次循环，获取最小的值
                for (Measurement measurement : measurementValleyList) {
                    if (measurement.getVal() < minVal) {
                        minVal = measurement.getVal();
                    }
                }
                //第二次循环，填充数据
                for (Measurement measurement : measurementValleyList) {
                    ElectricityDetail electricity = map.get(measurement.getDtime().toString());
                    electricity.setValley(measurement.getVal() - minVal);
                }
            }
        }
        return results;
    }

    /**
     * 根据条件获得电量对象列表（日）
     * @param deviceId 对象ID
     * @param dtime 时间范围
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<ElectricityDay> findElectricityDay(Long deviceId,
                                                       List<Date> dtime,
                                                       PageParam pageParam)
            throws ObjectNotFoundException {
        Specification spec = getSpecification(deviceId, dtime);
        if (QueryUtil.needPaging(pageParam)) {
            return electricityDayRepository.findAll(spec, QueryUtil.getPageRequest(pageParam));
        } else {
            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
            if (sort != null) {
                return electricityDayRepository.findAll(spec, sort);
            } else {
                return electricityDayRepository.findAll(spec);
            }
        }
    }

    /**
     * 根据条件获得电量对象列表（月）
     * @param deviceId 对象ID
     * @param dtime 时间范围
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<ElectricityMonth> findElectricityMonth(Long deviceId,
                                                           List<Date> dtime,
                                                           PageParam pageParam)
            throws ObjectNotFoundException {
        Specification spec = getSpecification(deviceId, dtime);
        if (QueryUtil.needPaging(pageParam)) {
            return electricityMonthRepository.findAll(spec, QueryUtil.getPageRequest(pageParam));
        } else {
            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
            if (sort != null) {
                return electricityMonthRepository.findAll(spec, sort);
            } else {
                return electricityMonthRepository.findAll(spec);
            }
        }
    }

    /**
     * 获得对象当日电量
     * @param deviceId 设备ID
     * @param pointDataType 点号类型
     */
    @Override
    public Double getLastDetail(Long deviceId, String pointDataType) throws ObjectNotFoundException {
        if (pointDataType == null) {
            pointDataType = DeviceConsts.POINT_DATA_TYPE.PowerAll.value();
        }
        Double lastValue = getAmount(deviceId, pointDataType);
        Double startValue = 0d;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date startTtime = calendar.getTime();
        calendar.setTimeInMillis(calendar.getTimeInMillis() + 1000 * 60 * 60 * 24);
        Date endDtime = calendar.getTime();
        List<Date> dtimeList = new ArrayList<>();
        dtimeList.add(startTtime);
        dtimeList.add(endDtime);
        //查询正向有功总电度
        Analog powerAllAnalog = deviceClient.getAnalogsByDevIdAndTypeCode(
                deviceId, pointDataType, null,null).getBody().getResults();
        if(powerAllAnalog != null){
            //通过点号和日期查询历史量测数据
            List<Measurement> measurements = measHistoryClient.getMeasurements(
                    powerAllAnalog.getPointNumber(), dtimeList,
                    getPageParamMap(null)).getBody().getResults();
            if(CollectionUtil.isNotEmpty(measurements)){
                startValue = measurements.get(0).getVal();
                BigDecimal last = BigDecimal.valueOf(lastValue);
                BigDecimal start = BigDecimal.valueOf(startValue);
                return last.subtract(start).doubleValue();
            }else {
                return 0d;
            }
        }else {
            return 0d;
        }
    }

    /**
     * 获得时间段的电量总和
     * @param deviceId 设备ID
     * @param dtime 日期
     * @param type 电量类型
     */
    @Override
    public Double getDayCount(Long deviceId,
                              List<Date> dtime,
                              EnergyConsts.ELECTRICITY_TYPE type)
            throws ObjectNotFoundException {
        Double currentValue = 0d;
        List<ElectricityDay> list = (List<ElectricityDay>) findElectricityDay(deviceId, dtime, new PageParam());
        if (list != null && list.size() > 0) {
            for (ElectricityDay item : list) {
                if (type == null || type == EnergyConsts.ELECTRICITY_TYPE.All) {
                    currentValue += item.getVal();
                } else if (type == EnergyConsts.ELECTRICITY_TYPE.Sharp) {
                    currentValue += item.getSharp();
                } else if (type == EnergyConsts.ELECTRICITY_TYPE.Peak) {
                    currentValue += item.getPeak();
                } else if (type == EnergyConsts.ELECTRICITY_TYPE.Flat) {
                    currentValue += item.getFlat();
                } else if (type == EnergyConsts.ELECTRICITY_TYPE.Valley) {
                    currentValue += item.getValley();
                }
            }
        }
        //添加当日电量
        if (isCurrentDay(dtime.get(dtime.size() - 1))) {
            currentValue += getLastDetail(deviceId, getPointDateTypeByElecType(type));
        }
        return currentValue;
    }

    private boolean isCurrentDay(Date dtime) {
        if (dtime == null) {
            return false;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return dtime.getTime() >= calendar.getTimeInMillis();
    }

    private String getPointDateTypeByElecType(EnergyConsts.ELECTRICITY_TYPE type) {
        if (type == null || type == EnergyConsts.ELECTRICITY_TYPE.All) {
            return DeviceConsts.POINT_DATA_TYPE.PowerAll.value();
        } else if (type == EnergyConsts.ELECTRICITY_TYPE.Sharp) {
            return DeviceConsts.POINT_DATA_TYPE.PowerSharp.value();
        } else if (type == EnergyConsts.ELECTRICITY_TYPE.Peak) {
            return DeviceConsts.POINT_DATA_TYPE.PowerPeak.value();
        } else if (type == EnergyConsts.ELECTRICITY_TYPE.Flat) {
            return DeviceConsts.POINT_DATA_TYPE.PowerFlat.value();
        } else if (type == EnergyConsts.ELECTRICITY_TYPE.Valley) {
            return DeviceConsts.POINT_DATA_TYPE.PowerValley.value();
        }
        return DeviceConsts.POINT_DATA_TYPE.PowerAll.value();
    }

    /**
     * 获得设备累计电量
     * @param deviceId 设备ID
     * @param pointDataType 点号类型
     */
    private Double getAmount(Long deviceId, String pointDataType) throws ObjectNotFoundException {
        Double lastValue = 0d;
        if (deviceId == null) {
            return lastValue;
        }
        Long pointNumber = getElectricityPointNumber(deviceId, pointDataType);
        if (pointNumber != null) {
            Map<Long, Double> realtime = measRealtimeClient.getMeasureRealtime(Collections.singletonList(pointNumber)).getBody().getResults();
            if (realtime != null && realtime.size() > 0) {
                lastValue = realtime.get(pointNumber);
            }
        }
        return lastValue;
    }

    /**
     * 获得企业能耗排名（月）
     * @param firmId 单位ID
     * @param stationId 电站ID
     * @param dtime 日期
     */
    @Override
    public List<CompanySort> getCompanyMonthSort(Long firmId,
                                                 Long stationId,
                                                 Date dtime,
                                                 PageParam pageParam) {
        List<Company> companys = authorityClient.getCompanys(
                firmId, stationId).getBody().getResults();
        List<Long> deviceIds = new ArrayList<>();
        Map<Long, String> companyIdTitleMap = new HashMap<>();
        if (companys != null && companys.size() > 0) {
            for (Company company : companys) {
                deviceIds.add(company.getId());
                companyIdTitleMap.put(company.getId(), company.getAbbreviation());
            }
        }
        Page<ElectricityMonth> electricityMonths = electricityMonthRepository.findByDtimeAndDeviceIdIn(dtime, deviceIds, QueryUtil.getPageRequest(pageParam));
        List<CompanySort> result = new ArrayList<>();
        if (electricityMonths != null && electricityMonths.getSize() > 0) {
            for (ElectricityMonth electricityMonth : electricityMonths) {
                CompanySort companySort = new CompanySort();
                companySort.setCompanyId(electricityMonth.getDeviceId());
                companySort.setCompanyTitle(companyIdTitleMap.get(electricityMonth.getDeviceId()));
                companySort.setVal(electricityMonth.getVal());
                companySort.setDtime(electricityMonth.getDtime());
                result.add(companySort);
            }
        }
        return result;
    }

}
